package cn.thornbird.orgsync.util;

import eu.bitwalker.useragentutils.UserAgent;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.lionsoul.ip2region.xdb.Searcher;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.util.FileCopyUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;

@Slf4j
public class IpUtil {

    private static final String LOCAL_IP = "127.0.0.1";

    private static Searcher searcher = null;

    static {
        try {
            InputStream inputStream = IpUtil.class.getResourceAsStream("/ip2region/ip2region.xdb");
            byte[] bytes = FileCopyUtils.copyToByteArray(inputStream);
            searcher = Searcher.newWithBuffer(bytes);
        } catch (IOException e) {
            log.error("error", e);
        }
    }

    public static String getClientIpAddress(HttpServletRequest request, Authentication authentication) {
        String ip = request.getHeader("X-Forwarded-For");
        if (checkIp(ip)) {
            if (ip.contains(",")) {
                ip = ip.split(",")[0];
            } else {
                ip = null;
            }
        }
        if (!checkIp(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (!checkIp(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (!checkIp(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (!checkIp(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (!checkIp(ip)) {
            ip = request.getHeader("X-Real-IP");
        }
        if (!checkIp(ip)) {
            ip = request.getRemoteAddr();
        }
        if (StringUtils.isEmpty(ip)) {
            ip = ((WebAuthenticationDetails) authentication.getDetails()).getRemoteAddress();
        }
        ip = StringUtils.isEmpty(ip) ? "" : ip;
        ip = "0:0:0:0:0:0:0:1".equals(ip) ? LOCAL_IP : ip;
        if (ip.equals(LOCAL_IP)) {
            InetAddress inetAddress;
            try {
                inetAddress = InetAddress.getLocalHost();
                ip = inetAddress.getHostAddress();
            } catch (UnknownHostException e) {
                log.error("error", e);
            }
        }
        return ip;
    }

    public static String getRegionInfo(String ip) {
        String regionInfo = null;
        if (searcher != null) {
            try {
                regionInfo = searcher.search(ip);
                if (!StringUtils.isEmpty(regionInfo)) {
                    regionInfo = regionInfo.replace("|0", "");
                    regionInfo = regionInfo.replace("0|", "");
                }
            } catch (Exception e) {
                log.error("error", e);
            }
        }
        return regionInfo;
    }

    public static String getUserAgentText(HttpServletRequest request) {
        String userAgent = request.getHeader("User-Agent");
        return StringUtils.isEmpty(userAgent) ? "" : userAgent;
    }

    public static UserAgent getUserAgent(HttpServletRequest request) {
        return UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
    }

    private static boolean checkIp(String ip) {
        return !StringUtils.isEmpty(ip) && !ip.equalsIgnoreCase("unknown");
    }

}
